From 73d2af755b041fd1279f08da7f0fc357f5da8af8 Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Thu, 7 May 2020 06:31:39 -0600 Subject: [PATCH] fix nmea writer date bug. (#553) * fix nmea writer date bug. dates before 2000 were written with a month off by one. This also changes the behavior when the creation time is invalid. Previously you would get data related to the unix epoch for the date and time fields. Now you get empty fields, i.e. ",," * fix magellan writer date bug. This had the same bug as nmea. It had an additional bug when it attempted to round the fractional part of a second. Rounding can ripple all the way from the fractional part of a second to the year, as is now demonstrated in the testcase. Like nmea, magellan will now print empty fields if the creation time is invalid. * fix date bug in gpssim. This is the same bug as in nmea, magproto. --- gpssim.cc | 8 ++-- magproto.cc | 35 ++++++-------- nmea.cc | 25 ++++------ reference/track/magellandate.log | 7 +++ reference/track/nmeadate.gpssim | 12 +++++ reference/track/nmeadate.gpx | 81 ++++++++++++++++++++++++++++++++ reference/track/nmeadate.nmea | 24 ++++++++++ testo.d/gpssim.test | 3 ++ testo.d/magellan.test | 2 + testo.d/nmea.test | 3 ++ 10 files changed, 160 insertions(+), 40 deletions(-) create mode 100644 reference/track/magellandate.log create mode 100644 reference/track/nmeadate.gpssim create mode 100644 reference/track/nmeadate.gpx create mode 100644 reference/track/nmeadate.nmea diff --git a/gpssim.cc b/gpssim.cc index 36efa4f17..a7ade0980 100644 --- a/gpssim.cc +++ b/gpssim.cc @@ -125,12 +125,10 @@ gpssim_write_pt(const Waypoint* wpt) if (wpt->creation_time.isValid()) { char tbuf[20]; - const time_t tt = wpt->GetCreationTime().toTime_t(); - struct tm* tm = gmtime(&tt); - int hms = tm->tm_hour * 10000 + tm->tm_min * 100 + tm->tm_sec; - int ymd = tm->tm_mday * 10000 + tm->tm_mon * 100 + tm->tm_year; + QByteArray dmy = wpt->GetCreationTime().toUTC().toString("ddMMyy").toUtf8(); + QByteArray hms = wpt->GetCreationTime().toUTC().toString("hhmmss").toUtf8(); - snprintf(tbuf, sizeof(tbuf), ",%d,%d",ymd, hms); + snprintf(tbuf, sizeof(tbuf), ",%s,%s",dmy.constData(), hms.constData()); strcat(obuf, tbuf); } diff --git a/magproto.cc b/magproto.cc index 3b917c6d8..6a968b5c1 100644 --- a/magproto.cc +++ b/magproto.cc @@ -20,6 +20,7 @@ */ +#include // for assert #include // for isprint, toupper #include // for fabs, lround #include // for sscanf, size_t @@ -28,7 +29,7 @@ #include // for gmtime #include // for QByteArray -#include // for QCharRef +#include // for QDateTime #include // for QDir, operator|, QDir::Files, QDir::Name, QDir::Readable #include // for QFileInfo #include // for QFileInfoList @@ -38,6 +39,7 @@ #include // for QString, operator== #include // for QStringList #include // for QTime +#include // for QVector #include // for CaseInsensitive #include // for qPrintable, foreach @@ -1407,27 +1409,20 @@ static void mag_track_disp(const Waypoint* waypointp) { QScopedPointer obuf; - int hms=0; - int fracsec=0; - int date=0; double ilat = waypointp->latitude; double ilon = waypointp->longitude; - struct tm* tm = nullptr; + + QByteArray dmy(""); + QByteArray hms(""); if (waypointp->creation_time.isValid()) { - const time_t ct = waypointp->GetCreationTime().toTime_t(); - tm = gmtime(&ct); - if (tm) { - hms = tm->tm_hour * 10000 + tm->tm_min * 100 + - tm->tm_sec; - date = tm->tm_mday * 10000 + tm->tm_mon * 100 + - tm->tm_year; - fracsec = lround(waypointp->GetCreationTime().time().msec()/10.0); - } - } - if (!tm) { - date = 0; - fracsec = 0; + // Round to hundredths of seconds before conversion to string. + // Rounding can ripple all the way from the msec to the year. + QDateTime dt = waypointp->GetCreationTime().toUTC(); + dt = dt.addMSecs(10 * lround(dt.time().msec()/10.0) - dt.time().msec()); + assert((dt.time().msec() % 10) == 0); + dmy = dt.toString("ddMMyy").toUtf8(); + hms = dt.toString("hhmmss.zzz").left(9).toUtf8(); } double lon = fabs(ilon); @@ -1442,12 +1437,12 @@ void mag_track_disp(const Waypoint* waypointp) lon = (lon_deg * 100.0 + lon); lat = (lat_deg * 100.0 + lat); - xasprintf(obuf,"PMGNTRK,%4.3f,%c,%09.3f,%c,%05.0f,%c,%06d.%02d,A,,%06d", + xasprintf(obuf,"PMGNTRK,%4.3f,%c,%09.3f,%c,%05.0f,%c,%s,A,,%s", lat, ilat < 0 ? 'S' : 'N', lon, ilon < 0 ? 'W' : 'E', waypointp->altitude == unknown_alt ? 0 : waypointp->altitude, - 'M', hms, fracsec, date); + 'M', hms.constData(), dmy.constData()); mag_writemsg(obuf.data()); } diff --git a/nmea.cc b/nmea.cc index 65cc8ca18..3366bdcc4 100644 --- a/nmea.cc +++ b/nmea.cc @@ -1199,8 +1199,6 @@ NmeaFormat::nmea_trackpt_pr(const Waypoint* wpt) char obuf[200]; char fix='0'; int cksum; - time_t hms; - time_t ymd; if (opt_sleep) { gbfflush(file_out); @@ -1220,14 +1218,11 @@ NmeaFormat::nmea_trackpt_pr(const Waypoint* wpt) double lat = degrees2ddmm(wpt->latitude); double lon = degrees2ddmm(wpt->longitude); - time_t ct = wpt->GetCreationTime().toTime_t(); - struct tm* tm = gmtime(&ct); - if (tm) { - hms = tm->tm_hour * 10000 + tm->tm_min * 100 + tm->tm_sec; - ymd = tm->tm_mday * 10000 + tm->tm_mon * 100 + tm->tm_year; - } else { - hms = 0; - ymd = 0; + QByteArray dmy(""); + QByteArray hms(""); + if (wpt->GetCreationTime().isValid()) { + dmy = wpt->GetCreationTime().toUTC().toString("ddMMyy").toUtf8(); + hms = wpt->GetCreationTime().toUTC().toString("hhmmss.zzz").toUtf8(); } switch (wpt->fix) { @@ -1246,14 +1241,14 @@ NmeaFormat::nmea_trackpt_pr(const Waypoint* wpt) } if (opt_gprmc) { - snprintf(obuf, sizeof(obuf), "GPRMC,%010.3f,%c,%08.3f,%c,%09.3f,%c,%.2f,%.2f,%06d,,", - (double) hms + (wpt->GetCreationTime().time().msec() / 1000.0), + snprintf(obuf, sizeof(obuf), "GPRMC,%s,%c,%08.3f,%c,%09.3f,%c,%.2f,%.2f,%s,,", + hms.constData(), fix=='0' ? 'V' : 'A', fabs(lat), lat < 0 ? 'S' : 'N', fabs(lon), lon < 0 ? 'W' : 'E', WAYPT_HAS(wpt, speed) ? MPS_TO_KNOTS(wpt->speed):(0), WAYPT_HAS(wpt, course) ? (wpt->course):(0), - (int) ymd); + dmy.constData()); cksum = nmea_cksum(obuf); /* GISTeq doesn't care about the checksum, but wants this prefixed, so @@ -1265,8 +1260,8 @@ NmeaFormat::nmea_trackpt_pr(const Waypoint* wpt) gbfprintf(file_out, "$%s*%02X\n", obuf, cksum); } if (opt_gpgga) { - snprintf(obuf, sizeof(obuf), "GPGGA,%010.3f,%08.3f,%c,%09.3f,%c,%c,%02d,%.1f,%.3f,M,%.1f,M,,", - (double) hms + (wpt->GetCreationTime().time().msec() / 1000.0), + snprintf(obuf, sizeof(obuf), "GPGGA,%s,%08.3f,%c,%09.3f,%c,%c,%02d,%.1f,%.3f,M,%.1f,M,,", + hms.constData(), fabs(lat), lat < 0 ? 'S' : 'N', fabs(lon), lon < 0 ? 'W' : 'E', fix, diff --git a/reference/track/magellandate.log b/reference/track/magellandate.log new file mode 100644 index 000000000..48516506f --- /dev/null +++ b/reference/track/magellandate.log @@ -0,0 +1,7 @@ +$PMGNTRK,4231.829,N,08807.303,W,00210,M,032908.38,A,,070898*64 +$PMGNTRK,4231.829,N,08807.303,W,00210,M,032909.38,A,,070899*64 +$PMGNTRK,4231.829,N,08807.304,W,00210,M,032910.38,A,,070800*6B +$PMGNTRK,4231.829,N,08807.304,W,00210,M,032911.38,A,,070801*6B +$PMGNTRK,4231.829,N,08807.304,W,00210,M,032912.38,A,,070802*6B +$PMGNTRK,4231.829,N,08807.304,W,00210,M,000000.00,A,,010103*65 +$PMGNCMD,END*3D diff --git a/reference/track/nmeadate.gpssim b/reference/track/nmeadate.gpssim new file mode 100644 index 000000000..586a499b7 --- /dev/null +++ b/reference/track/nmeadate.gpssim @@ -0,0 +1,12 @@ +$FRSPD,0.16*66 +$FRWPT,4231.82910,N,08807.30330,W,209.8,070898,032908*63 +$FRSPD,0.16*66 +$FRWPT,4231.82910,N,08807.30340,W,209.7,070899,032909*6B +$FRSPD,0.16*66 +$FRWPT,4231.82920,N,08807.30360,W,209.7,070800,032910*62 +$FRSPD,0.22*61 +$FRWPT,4231.82920,N,08807.30360,W,209.6,070801,032911*63 +$FRSPD,0.16*66 +$FRWPT,4231.82920,N,08807.30370,W,209.6,070802,032912*62 +$FRSPD,0.16*66 +$FRWPT,4231.82930,N,08807.30380,W,209.6,311202,235959*68 diff --git a/reference/track/nmeadate.gpx b/reference/track/nmeadate.gpx new file mode 100644 index 000000000..d11ded605 --- /dev/null +++ b/reference/track/nmeadate.gpx @@ -0,0 +1,81 @@ + + + + + + + + 209.800 + + 138.919998 + 0.083333 + -34.2 + 2d + 5 + 1.600000 + 4.500000 + 4.900000 + + + 209.700 + + 145.850006 + 0.083333 + -34.2 + 3d + 6 + 1.600000 + 4.500000 + 4.900000 + + + 209.700 + + 143.250000 + 0.083333 + -34.2 + dgps + 7 + 1.600000 + 4.500000 + 4.900000 + + + 209.600 + + 145.759995 + 0.111111 + -34.2 + pps + 8 + 1.600000 + 4.600000 + 4.900000 + + + 209.600 + + 141.440002 + 0.083333 + -34.2 + 2d + 9 + 1.600000 + 4.600000 + 4.900000 + + + 209.600 + + 140.399994 + 0.083333 + -34.2 + 3d + 5 + 1.600000 + 4.600000 + 4.900000 + + + + diff --git a/reference/track/nmeadate.nmea b/reference/track/nmeadate.nmea new file mode 100644 index 000000000..951eca6c8 --- /dev/null +++ b/reference/track/nmeadate.nmea @@ -0,0 +1,24 @@ +$GPRMC,032908.379,A,4231.829,N,08807.303,W,0.16,138.92,070898,,*14 +$GPGGA,032908.379,4231.829,N,08807.303,W,1,05,1.6,209.800,M,-34.2,M,,*6A +$GPVTG,138.920,T,0,M,0.162,N,0.300,K*57 +$GPGSA,A,2,,,,,,,,,,,,,4.9,1.6,4.5*38 +$GPRMC,032909.379,A,4231.829,N,08807.303,W,0.16,145.85,070899,,*18 +$GPGGA,032909.379,4231.829,N,08807.303,W,1,06,1.6,209.700,M,-34.2,M,,*67 +$GPVTG,145.850,T,0,M,0.162,N,0.300,K*5B +$GPGSA,A,3,,,,,,,,,,,,,4.9,1.6,4.5*39 +$GPRMC,032910.379,A,4231.829,N,08807.304,W,0.16,143.25,070800,,*1B +$GPGGA,032910.379,4231.829,N,08807.304,W,2,07,1.6,209.700,M,-34.2,M,,*6A +$GPVTG,143.250,T,0,M,0.162,N,0.300,K*57 +$GPGSA,A,3,,,,,,,,,,,,,4.9,1.6,4.5*39 +$GPRMC,032911.379,A,4231.829,N,08807.304,W,0.22,145.76,070801,,*1C +$GPGGA,032911.379,4231.829,N,08807.304,W,3,08,1.6,209.600,M,-34.2,M,,*64 +$GPVTG,145.760,T,0,M,0.216,N,0.400,K*50 +$GPGSA,A,*03 +$GPRMC,032912.379,A,4231.829,N,08807.304,W,0.16,141.44,070802,,*1E +$GPGGA,032912.379,4231.829,N,08807.304,W,1,09,1.6,209.600,M,-34.2,M,,*64 +$GPVTG,141.440,T,0,M,0.162,N,0.300,K*52 +$GPGSA,A,2,,,,,,,,,,,,,4.9,1.6,4.6*3B +$GPRMC,235959.999,A,4231.829,N,08807.304,W,0.16,140.40,311202,,*1B +$GPGGA,235959.999,4231.829,N,08807.304,W,1,05,1.6,209.600,M,-34.2,M,,*66 +$GPVTG,140.400,T,0,M,0.162,N,0.300,K*57 +$GPGSA,A,3,,,,,,,,,,,,,4.9,1.6,4.6*3A diff --git a/testo.d/gpssim.test b/testo.d/gpssim.test index b4e64141c..175c774e8 100644 --- a/testo.d/gpssim.test +++ b/testo.d/gpssim.test @@ -5,3 +5,6 @@ gpsbabel -i geo -f ${REFERENCE}/geocaching.loc -o gpssim -F ${TMPDIR}/waypoints. compare ${TMPDIR}/waypoints.gpssim ${REFERENCE} gpsbabel -i gpx -f ${REFERENCE}/track/tracks.gpx -o gpssim -F ${TMPDIR}/tracks.gpssim compare ${TMPDIR}/tracks.gpssim ${REFERENCE}/track +gpsbabel -i gpx -f ${REFERENCE}/track/nmeadate.gpx -o gpssim -F ${TMPDIR}/nmeadate.gpssim +compare ${REFERENCE}/track/nmeadate.gpssim ${TMPDIR}/nmeadate.gpssim + diff --git a/testo.d/magellan.test b/testo.d/magellan.test index b76fa4e32..f6f4e80c1 100644 --- a/testo.d/magellan.test +++ b/testo.d/magellan.test @@ -18,3 +18,5 @@ gpsbabel -r -i magellanx -f ${REFERENCE}/route/magexplorist.rte -o magellanx -F gpsbabel -r -i magellanx -f ${TMPDIR}/magxfile.rte -o magellanx -F ${TMPDIR}/magxfile2.rte compare ${REFERENCE}/route/magexplorist.rte ${TMPDIR}/magxfile2.rte +gpsbabel -t -i gpx -f ${REFERENCE}/track/nmeadate.gpx -o magellanx -F ${TMPDIR}/magellandate.log +compare ${REFERENCE}/track/magellandate.log ${TMPDIR}/magellandate.log diff --git a/testo.d/nmea.test b/testo.d/nmea.test index 169682979..3ef9e647f 100644 --- a/testo.d/nmea.test +++ b/testo.d/nmea.test @@ -28,3 +28,6 @@ gpsbabel -t -i nmea -f ${REFERENCE}/track/backfilldate.nmea -o unicsv,utc=0 -F $ compare ${REFERENCE}/track/backfilldate.csv ${TMPDIR}/backfilldate.csv gpsbabel -t -i nmea -f ${REFERENCE}/track/backfilldate2.nmea -o unicsv,utc=0 -F ${TMPDIR}/backfilldate2.csv compare ${REFERENCE}/track/backfilldate2.csv ${TMPDIR}/backfilldate2.csv + +gpsbabel -i gpx -f ${REFERENCE}/track/nmeadate.gpx -o nmea -F ${TMPDIR}/nmeadate.nmea +compare ${REFERENCE}/track/nmeadate.nmea ${TMPDIR}/nmeadate.nmea -- 2.30.2